package com.mindata.blockchain.socket.common.queue;

import com.mindata.blockchain.ApplicationContextProvider;
import com.mindata.blockchain.block.block.BlockBody;
import com.mindata.blockchain.block.instruction.Instruction;
import com.mindata.blockchain.common.CommonUtil;
import com.mindata.blockchain.socket.common.event.LeaderUpdateEvent;
import com.mindata.blockchain.socket.common.queue.base.AbstractInstructionsMsgQueue;
import com.mindata.blockchain.core.manager.DbBlockManager;
import com.mindata.blockchain.core.requestbody.BlockRequestBody;
import com.mindata.blockchain.core.service.BlockService;
import com.mindata.blockchain.socket.client.ClientStarter;
import com.mindata.blockchain.socket.client.PacketSender;
import com.mindata.blockchain.socket.common.Const;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.tio.core.Node;

import javax.annotation.Resource;
import java.util.ArrayList;

@Component
public class InstructionQueue extends AbstractInstructionsMsgQueue {
    @Value("${publicKey}")
    String publicKey;
    @Value("${privateKey}")
    String privateKey;
    @Resource
    BlockService blockService;
    @Value("${singeNode}")
    boolean singeNode;
    @Value("${tioPort}")
    int PORT;
    @Resource
    private PacketSender packetSender;

    private Logger logger = LoggerFactory.getLogger(InstructionQueue.class);

    @Override
    public void deal() {
        //判断是否能打包若是则执行打包区块进行共识
        if (!singeNode) {
            int concensusindex = (dbBlockManager.getLastDGLBlockNumber() + 1) % commonValue.getGroupsize();
//            logger.warn("共识序列号为{},节点序号为{}", concensusindex, commonValue.getNodeIndex());
            if (concensusindex != commonValue.getNodeIndex()) {
                logger.error("不能出块");
                return;
            }
        }
        // 当map中未处理的交易大于区块交易limit是生成区块
//        logger.error("判断是否打包区块");
        if (singeNode || txMsgConcurrentHashMap.size() >= commonValue.getBlockTxLimit()) {
            BlockRequestBody blockRequestBody = new BlockRequestBody();
            blockRequestBody.setPublicKey(publicKey);
            BlockBody blockBody = new BlockBody();
            ArrayList<Instruction> instructions = new ArrayList<>();
            ArrayList<Instruction> inter_instructions = new ArrayList<>();
            ArrayList<Instruction> intro_instructions = new ArrayList<>();
            int size = 0;
            if (singeNode) {
                size = Math.min(instructionConcurrentLinkedQueue.size(), commonValue.getBlockTxLimit());
            } else {
                size = commonValue.getBlockTxLimit();
            }
            for (int i = 0; i < size; i++) {
                Instruction ins;
                do {
                    ins = instructionConcurrentLinkedQueue.poll();
                } while (ins == null);
                // 提出BlockTxLimit个instruction打包
                if (!ins.isIntro()) {
                    inter_instructions.add(ins);
                } else {
                    intro_instructions.add(ins);
                }
                instructions.add(ins);
                txStateConcurrentHashMap.put(ins.getHash(), true);
                txMsgConcurrentHashMap.remove(ins.getHash());
            }
            blockBody.setInstructions(instructions);
            blockBody.setInter_instructions(inter_instructions);
            blockBody.setIntro_instructions(intro_instructions);
            blockRequestBody.setBlockBody(blockBody);
            logger.error("是leader,并开始出块");
            blockService.addBlock(blockRequestBody);
        }
    }
}
